<template>
  <div class="transition-manager">
    <transition
      :name="currentTransition.name"
      :mode="currentTransition.mode"
      :duration="currentTransition.duration"
      @before-enter="handleBeforeEnter"
      @enter="handleEnter"
      @after-enter="handleAfterEnter"
      @before-leave="handleBeforeLeave"
      @leave="handleLeave"
      @after-leave="handleAfterLeave"
    >
      <div
        :key="route.fullPath"
        class="page-container"
        :class="currentTransition.containerClass"
      >
        <slot />
      </div>
    </transition>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { defaultMatcher, type TransitionConfig } from './transitionConfig'

const route = useRoute()
const isTransitioning = ref(false)
const previousPath = ref('')

// 计算当前应该使用的转场效果
const currentTransition = computed((): TransitionConfig => {
  const currentPath = route.path
  const fromPath = previousPath.value || '/'
  
  // 使用转场匹配器获取合适的转场效果
  return defaultMatcher.match(fromPath, currentPath)
})

// 监听路由变化
watch(() => route.path, async (newPath, oldPath) => {
  if (newPath !== oldPath) {
    previousPath.value = oldPath
    
    // 设置转场状态
    isTransitioning.value = true
    
    // 等待DOM更新
    await nextTick()
    
    // 延迟重置转场状态
    setTimeout(() => {
      isTransitioning.value = false
    }, currentTransition.value.duration + 100)
  }
})

// 转场生命周期处理
const handleBeforeEnter = (el: Element) => {
  const element = el as HTMLElement
  applyInitialStyles(element)
}

const handleEnter = (el: Element) => {
  const element = el as HTMLElement
  applyEnterStyles(element)
}

const handleAfterEnter = (el: Element) => {
  const element = el as HTMLElement
  cleanupStyles(element)
}

const handleBeforeLeave = (el: Element) => {
  const element = el as HTMLElement
  applyLeaveStyles(element)
}

const handleLeave = () => {
  // 转场动画逻辑已在CSS中处理
}

const handleAfterLeave = (el: Element) => {
  const element = el as HTMLElement
  cleanupStyles(element)
}

// 应用初始样式
const applyInitialStyles = (element: HTMLElement) => {
  const transition = currentTransition.value
  
  switch (transition.name) {
    case 'slide-left':
      element.style.transform = 'translateX(100%)'
      element.style.opacity = '0'
      break
    case 'slide-right':
      element.style.transform = 'translateX(-100%)'
      element.style.opacity = '0'
      break
    case 'scale-up':
      element.style.transform = 'scale(0.95) translateY(20px)'
      element.style.opacity = '0'
      break
    case 'scale-down':
      element.style.transform = 'scale(1.05) translateY(-20px)'
      element.style.opacity = '0'
      break
    case 'slide-up':
      element.style.transform = 'translateY(100%)'
      element.style.opacity = '0'
      break
    case 'slide-down':
      element.style.transform = 'translateY(-100%)'
      element.style.opacity = '0'
      break
    case 'fade':
      element.style.opacity = '0'
      break
    case 'flip':
      element.style.transform = 'rotateY(-90deg)'
      element.style.opacity = '0'
      break
    case 'flip-3d':
      element.style.transform = 'rotateY(-90deg) rotateX(10deg)'
      element.style.opacity = '0'
      break
    default:
      element.style.transform = 'translateX(100%)'
      element.style.opacity = '0'
  }
  
  element.style.transition = `all ${transition.duration}ms ${transition.easing || 'cubic-bezier(0.25, 0.46, 0.45, 0.94)'}`
  
  if (transition.delay) {
    element.style.transitionDelay = `${transition.delay}ms`
  }
}

// 应用进入样式
const applyEnterStyles = (element: HTMLElement) => {
  requestAnimationFrame(() => {
    element.style.transform = 'translateX(0) scale(1) translateY(0) rotateY(0deg) rotateX(0deg)'
    element.style.opacity = '1'
  })
}

// 应用离开样式
const applyLeaveStyles = (element: HTMLElement) => {
  const transition = currentTransition.value
  
  switch (transition.name) {
    case 'slide-left':
      element.style.transform = 'translateX(-100%)'
      element.style.opacity = '0'
      break
    case 'slide-right':
      element.style.transform = 'translateX(100%)'
      element.style.opacity = '0'
      break
    case 'scale-up':
      element.style.transform = 'scale(1.05) translateY(-20px)'
      element.style.opacity = '0'
      break
    case 'scale-down':
      element.style.transform = 'scale(0.95) translateY(20px)'
      element.style.opacity = '0'
      break
    case 'slide-up':
      element.style.transform = 'translateY(-100%)'
      element.style.opacity = '0'
      break
    case 'slide-down':
      element.style.transform = 'translateY(100%)'
      element.style.opacity = '0'
      break
    case 'fade':
      element.style.opacity = '0'
      break
    case 'flip':
      element.style.transform = 'rotateY(90deg)'
      element.style.opacity = '0'
      break
    case 'flip-3d':
      element.style.transform = 'rotateY(90deg) rotateX(-10deg)'
      element.style.opacity = '0'
      break
    default:
      element.style.transform = 'translateX(-100%)'
      element.style.opacity = '0'
  }
}

// 清理样式
const cleanupStyles = (element: HTMLElement) => {
  element.style.transform = ''
  element.style.opacity = ''
  element.style.transition = ''
  element.style.transitionDelay = ''
}
</script>

<style scoped>
.transition-manager {
  position: relative;
  width: 100%;
  height: 100%;
}

.page-container {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: #f5f5f5;
}

/* 滑动转场效果 */
.slide-left-transition,
.slide-right-transition,
.scale-up-transition,
.scale-down-transition,
.slide-up-transition,
.slide-down-transition,
.fade-transition,
.flip-transition,
.flip-3d-transition {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: #f5f5f5;
}

/* 水平滑动 */
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
  transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  position: relative;
}

.slide-left-enter-from {
  transform: translateX(100%);
  opacity: 0;
}

.slide-left-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}

.slide-right-enter-from {
  transform: translateX(-100%);
  opacity: 0;
}

.slide-right-leave-to {
  transform: translateX(100%);
  opacity: 0;
}

/* 缩放转场效果 */
.scale-up-enter-active,
.scale-up-leave-active,
.scale-down-enter-active,
.scale-down-leave-active {
  transition: all 0.35s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  position: relative;
}

.scale-up-enter-from {
  transform: scale(0.95) translateY(20px);
  opacity: 0;
}

.scale-up-leave-to {
  transform: scale(1.05) translateY(-20px);
  opacity: 0;
}

.scale-down-enter-from {
  transform: scale(1.05) translateY(-20px);
  opacity: 0;
}

.scale-down-leave-to {
  transform: scale(0.95) translateY(20px);
  opacity: 0;
}

/* 垂直滑动转场效果 */
.slide-up-enter-active,
.slide-up-leave-active,
.slide-down-enter-active,
.slide-down-leave-active {
  transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  position: relative;
}

.slide-up-enter-from {
  transform: translateY(100%);
  opacity: 0;
}

.slide-up-leave-to {
  transform: translateY(-100%);
  opacity: 0;
}

.slide-down-enter-from {
  transform: translateY(-100%);
  opacity: 0;
}

.slide-down-leave-to {
  transform: translateY(100%);
  opacity: 0;
}

/* 淡入淡出转场效果 */
.fade-enter-active,
.fade-leave-active {
  transition: all 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  position: relative;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

/* 翻转转场效果 */
.flip-enter-active,
.flip-leave-active {
  transition: all 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transform-style: preserve-3d;
  perspective: 1000px;
  position: relative;
}

.flip-enter-from {
  transform: rotateY(-90deg);
  opacity: 0;
}

.flip-leave-to {
  transform: rotateY(90deg);
  opacity: 0;
}

/* 3D翻转转场效果 */
.flip-3d-enter-active,
.flip-3d-leave-active {
  transition: all 0.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);
  transform-style: preserve-3d;
  perspective: 1000px;
  position: relative;
}

.flip-3d-enter-from {
  transform: rotateY(-90deg) rotateX(10deg);
  opacity: 0;
}

.flip-3d-leave-to {
  transform: rotateY(90deg) rotateX(-10deg);
  opacity: 0;
}

/* 默认转场效果 */
.default-transition {
  position: relative;
  width: 100%;
  min-height: 100vh;
  background: #f5f5f5;
}

.slide-enter-active,
.slide-leave-active {
  transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  position: relative;
}

.slide-enter-from {
  transform: translateX(100%);
  opacity: 0;
}

.slide-leave-to {
  transform: translateX(-100%);
  opacity: 0;
}

/* 移动端优化 */
@media (max-width: 768px) {
  .slide-left-enter-active,
  .slide-left-leave-active,
  .slide-right-enter-active,
  .slide-right-leave-active,
  .scale-up-enter-active,
  .scale-up-leave-active,
  .scale-down-enter-active,
  .scale-down-leave-active,
  .slide-up-enter-active,
  .slide-up-leave-active,
  .slide-down-enter-active,
  .slide-down-leave-active,
  .fade-enter-active,
  .fade-leave-active,
  .flip-enter-active,
  .flip-leave-active,
  .flip-3d-enter-active,
  .flip-3d-leave-active,
  .slide-enter-active,
  .slide-leave-active {
    transition-duration: 0.25s;
  }
}

/* 确保转场期间内容不会闪烁 */
.page-container[class*="-transition"] {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  will-change: transform, opacity;
}

/* 优化性能 */
.page-container {
  will-change: transform, opacity;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}

/* 转场期间的背景处理 */
.transition-manager {
  background: #f5f5f5;
  min-height: 100vh;
}

/* 确保转场期间页面内容可见 */
.page-container {
  background: inherit;
}

/* 转场完成后的状态 */
.page-container.transition-complete {
  background: transparent;
}
</style>
